package com.ayf.payment.game.api.service.impl;

import com.ayf.payment.game.api.PartitionRemoteService;
import com.ayf.payment.game.api.config.RequestConfig;
import com.ayf.payment.game.api.dto.*;
import com.ayf.payment.game.api.dto.criteria.ReissueRecordCriteria;
import com.ayf.payment.game.api.dto.criteria.ReissueRecordSelectCriteria;
import com.ayf.payment.game.api.dto.criteria.TemplateCriteria;
import com.ayf.payment.game.api.dto.getaway.CheckOrderIDGateWayDTO;
import com.ayf.payment.game.api.dto.getaway.GameRechargeGetWayCollectionDTO;
import com.ayf.payment.game.api.dto.getaway.GameRechargeGetWayDTO;
import com.ayf.payment.game.api.dto.getaway.ReplacementGetWayDTO;
import com.ayf.payment.game.api.dto.platform.MerchantReissueRecordDTO;
import com.ayf.payment.game.api.dto.platform.criteria.MerchantReissueRecordCriteria;
import com.ayf.payment.game.api.entity.*;
import com.ayf.payment.game.api.exception.ParameterException;
import com.ayf.payment.game.api.httpclient.HttpClientUtils;
import com.ayf.payment.game.api.mapper.ReissueRecordMapper;
import com.ayf.payment.game.api.service.*;
import com.ayf.payment.game.api.type.CommonConstants;
import com.ayf.payment.game.api.type.ReissueType;
import com.ayf.payment.game.api.utils.CommonResult;
import com.ayf.payment.game.api.utils.DateUtils;
import com.ayf.payment.game.api.utils.SerialNumberUtil;
import com.ayf.payment.game.api.utils.SnowFlakeUtils;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.swwx.charm.commons.lang.utils.BeanConvertUtils;
import com.swwx.charm.commons.lang.utils.LogPortal;
import org.apache.commons.lang.StringUtils;
import org.apache.dubbo.config.annotation.Reference;
import org.apache.poi.ss.formula.functions.T;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;

@Service
public class ReissueRecordServiceImpl implements ReissueRecordService {

    @Resource
    private ReissueRecordMapper reissueRecordMapper;

    @Resource
    private PartitionService partitionService;

    @Resource
    private ReissueAllTaskService reissueAllTaskService;

    @Resource
    private OrderService orderService;

    @Resource
    private TemplateService templateService;

    @Resource
    private MerchantService merchantService;


    @Reference(group = "xygpay-rpc",version = "1.0.0")
    private PartitionRemoteService partitionRemoteService;

    @Override
    public List<ReissueRecordDTO> selectByPage(ReissueRecordSelectCriteria selectCriteria) {
        if(StringUtils.isNotEmpty(selectCriteria.getStartTime())){
            selectCriteria.setStartTimeIndex(DateUtils.dateToInteger(DateUtils.stringToDate2(selectCriteria.getStartTime())));
        }
        if(StringUtils.isNotEmpty(selectCriteria.getEndTime())){
            selectCriteria.setEndTimeIndex(DateUtils.dateToInteger(DateUtils.stringToDate2(selectCriteria.getEndTime())));
        }
        return reissueRecordMapper.selectByPage(selectCriteria);
    }

    @Override
    public ReissueRecordVO selectTotalAmountByPage(ReissueRecordSelectCriteria selectCriteria) {
        if(StringUtils.isNotEmpty(selectCriteria.getStartTime())){
            selectCriteria.setStartTimeIndex(DateUtils.dateToInteger(DateUtils.stringToDate2(selectCriteria.getStartTime())));
        }
        if(StringUtils.isNotEmpty(selectCriteria.getEndTime())){
            selectCriteria.setEndTimeIndex(DateUtils.dateToInteger(DateUtils.stringToDate2(selectCriteria.getEndTime())));
        }
        return reissueRecordMapper.selectTotalAmountByPage(selectCriteria);
    }

    @Override
    public List<MerchantReissueRecordDTO> selectMerchantReissueRecordByPage(MerchantReissueRecordCriteria selectCriteria) {
        if(StringUtils.isNotEmpty(selectCriteria.getStartTime())){
            selectCriteria.setStartTimeIndex(DateUtils.dateToInteger(DateUtils.stringToDate2(selectCriteria.getStartTime())));
        }
        if(StringUtils.isNotEmpty(selectCriteria.getEndTime())){
            selectCriteria.setEndTimeIndex(DateUtils.dateToInteger(DateUtils.stringToDate2(selectCriteria.getEndTime())));
        }
        return reissueRecordMapper.selectMerchantReissueRecordByPage(selectCriteria);
    }

    @Override
    @Transactional
    public Map saveAuto(ReissueAllTaskDTO t) {
        if (t == null) {
            throw new ParameterException("参数不能为空");
        }
        if (StringUtils.isBlank(t.getPartitionId())) {
            throw new ParameterException("分区不能为空");
        }
        if (StringUtils.isBlank(t.getReissueStartTime()) || StringUtils.isBlank(t.getReissueEndTime())) {
            throw new ParameterException("日期不能为空");
        }
        if (t.getIsAutoReissue() == null) {
            throw new ParameterException("开启自动整区补发不能为空");
        }
        if (t.getIsAutoReissue() == 1) {
            if (StringUtils.isEmpty(t.getAutoReissueTime())) {
                throw new ParameterException("自动整区补发时间不能为空");
            }
        }
        if (StringUtils.isEmpty(t.getPartitionName())){
            PartitionDTO partitionDTO = partitionService.getPartitionInfoById(t.getPartitionId());
            if (partitionDTO != null){
                t.setPartitionName(partitionDTO.getPartitionName());
            }
        }
        ReissueAllTask reissueAllTask = BeanConvertUtils.convert(t, ReissueAllTask.class);
        reissueAllTask.setReissueStatus(0);
        reissueAllTaskService.save(reissueAllTask);
        return reissueAll(reissueAllTask,reissueAllTask.getIsAutoReissue());
    }

    public Map reissueAll(ReissueAllTask reissueAllTask,int isAutoReissue){
        if (reissueAllTask.getIsCleanData() == 1 && isAutoReissue==0) {
            boolean result = partitionService.cleanDataPartition(reissueAllTask.getMerchantId(), reissueAllTask.getPartitionId(),reissueAllTask.getOperateIp());
            if (!result) {
                reissueAllTask.setReissueStatus(-1);
                throw new ParameterException("充值网关服务异常，重新生成金额文件失败，请检查充值网关或稍后重试");
            }
        }
        Map map=new HashMap();
        try {
            Partition partition = partitionService.find(reissueAllTask.getMerchantId(), reissueAllTask.getPartitionId());
            boolean typeOne = false, typeTwo = false, typeThree = false;
            //手动冲值
            if (!StringUtils.isEmpty(reissueAllTask.getAutoType())) {
                if (reissueAllTask.getAutoType().indexOf("1") > -1) {
                    typeOne = true;
                }
                if (reissueAllTask.getAutoType().indexOf("2") > -1) {
                    typeTwo = true;
                }
                if (reissueAllTask.getAutoType().indexOf("3") > -1) {
                    typeThree = true;
                }
            }
            List<GameRechargeGetWayDTO> list = reissue(reissueAllTask, 1, 1000, typeOne, typeTwo, typeThree, partition,isAutoReissue);
            map.put("recharge", list.size());
            List<GameRechargeGetWayDTO> listManual =new ArrayList<>();
            if (typeOne) {
                ReissueRecordSelectCriteria selectCriteria = new ReissueRecordSelectCriteria();
                selectCriteria.setPartitionId(reissueAllTask.getPartitionId());
                selectCriteria.setMerchantId(reissueAllTask.getMerchantId());
                selectCriteria.setReissueType(ReissueType.MANUAL.name());
                selectCriteria.setStartTime(reissueAllTask.getReissueStartTime());
                selectCriteria.setEndTime(reissueAllTask.getReissueEndTime());
                if (reissueAllTask.getReissueStartTime().length() == 16) {
                    selectCriteria.setStartTimeIndex(DateUtils.dateToInteger(DateUtils.str2DateByFormat(reissueAllTask.getReissueStartTime(), "yyyy-MM-dd HH:mm")));
                } else {
                    selectCriteria.setStartTimeIndex(DateUtils.dateToInteger(DateUtils.stringToDate2(reissueAllTask.getReissueStartTime())));
                }
                if (reissueAllTask.getReissueEndTime().length() == 16) {
                    selectCriteria.setEndTimeIndex(DateUtils.dateToInteger(DateUtils.str2DateByFormat(reissueAllTask.getReissueEndTime(), "yyyy-MM-dd HH:mm")));
                } else {
                    selectCriteria.setEndTimeIndex(DateUtils.dateToInteger(DateUtils.stringToDate2(reissueAllTask.getReissueEndTime())));
                }
                selectCriteria.setScriptStatus(1);// 仅仅整区补发手动补发状态成功的
                selectCriteria.setExcludePlayerAccountNoList(reissueAllTask.getExcludePlayerAccountNoList());
                List<ReissueRecordDTO> reissueRecordList = reissueRecordMapper.selectByPage(selectCriteria);
                List<ReissueRecord> rrList = new ArrayList<>();
                for (ReissueRecordDTO rrDTO : reissueRecordList) {
                    ReissueRecord rr = new ReissueRecord();
                    rr.setRatId(reissueAllTask.getId());
                    rr.setMerchantId(reissueAllTask.getMerchantId());
                    rr.setOperatorId(reissueAllTask.getOperatorId());
                    rr.setPartitionId(reissueAllTask.getPartitionId());
                    rr.setPartitionName(reissueAllTask.getPartitionName());
                    rr.setReissueType(rrDTO.getReissueType());
                    rr.setCode(rrDTO.getPayCode());
                    Date date = new Date();
                    rr.setExchangeTime(date);
                    rr.setOperateIp(reissueAllTask.getOperateIp());
                    rr.setExchangeTimeIndex(DateUtils.dateToInteger(date));
                    rr.setSerialNumber("A".concat(SnowFlakeUtils.getUniqueId()));
                    rr.setScriptStatus(2);
                    rr.setReissueType(ReissueType.WHOLE);
                    rr.setRechargeNumber(rrDTO.getRechargeNumber());
                    rr.setRechargeAmount(rrDTO.getRechargeAmount());
                    rr.setOrderNo(rrDTO.getSerialNumber());
                    rr.setChannelName(rrDTO.getChannelName());
                    rr.setManualType(rrDTO.getManualType());
                    if(isAutoReissue == 0) {
                        reissueRecordMapper.insertSelective(rr);
                    }
                    rrList.add(rr);
                }
                listManual = rechargeAllByManual(rrList, reissueAllTask, typeTwo, typeThree, partition);
                map.put("manual", listManual.size());
            }
            if (isAutoReissue == 0) {
                list.addAll(listManual);
                rechargeAllGetWay(list, partition, reissueAllTask);
            }
        }finally {
            reissueAllTaskService.update(reissueAllTask);
            reissueRecordMapper.updateReissueAllTask(reissueAllTask.getId(),reissueAllTask.getReissueStatus());
        }
        return map;
    }

    private List<GameRechargeGetWayDTO> rechargeAllByManual(List<ReissueRecord> rrList, ReissueAllTask reissueAllTask, boolean typeTwo, boolean typeThree,Partition partition){
        if (CollectionUtils.isEmpty(rrList)) {
           return new ArrayList<>();
        }else{
            TemplateCriteria template = templateService.selectTemById(partition.getTemplateId());
            PartitionDTO partitionDTO = BeanConvertUtils.convert(partition, PartitionDTO.class);
            List<ReissueRecordD> rrDTOList = BeanConvertUtils.convert(rrList, ReissueRecordD.class);
            ReissueAllTaskDTO reissueAllTaskDTO = BeanConvertUtils.convert(reissueAllTask, ReissueAllTaskDTO.class);
            List<GameRechargeGetWayDTO> rechargelist = partitionRemoteService.rechargeAllGetWayByManual(rrDTOList, reissueAllTaskDTO, partitionDTO, template, typeTwo, typeThree);
            return rechargelist;
        }
    }

    private List<GameRechargeGetWayDTO> rechargeAll(List<ReissueRecord> rrList, ReissueAllTask reissueAllTask, boolean typeOne, boolean typeTwo, boolean typeThree,Partition partition){
            if (CollectionUtils.isEmpty(rrList)) {
                return new ArrayList<>();
            }
            TemplateCriteria template = templateService.selectTemById(partition.getTemplateId());
            PartitionDTO partitionDTO = BeanConvertUtils.convert(partition, PartitionDTO.class);
            List<ReissueRecordD> rrDTOList = BeanConvertUtils.convert(rrList, ReissueRecordD.class);
            ReissueAllTaskDTO reissueAllTaskDTO = BeanConvertUtils.convert(reissueAllTask, ReissueAllTaskDTO.class);
            List<GameRechargeGetWayDTO> rechargelist =partitionRemoteService.rechargeAllGetWay(rrDTOList, reissueAllTaskDTO, partitionDTO, template, typeOne, typeTwo, typeThree);
          return rechargelist;
        }

    public  List<GameRechargeGetWayDTO> reissue(ReissueAllTask t, Integer pageNum, Integer pageSize, boolean typeOne, boolean typeTwo, boolean typeThree,Partition partition,int isAutoReissue) {
        ReissueOrderDTO temp = new ReissueOrderDTO();
        temp.setPartitionId(t.getPartitionId());
        temp.setPageNum(pageNum);
        temp.setPageSize(pageSize);
        if (StringUtils.isNotEmpty(t.getReissueStartTime())) {
            temp.setOrderStartTime(t.getReissueStartTime());
            if (t.getReissueStartTime().length()==16){
                temp.setOrderStartIndex(DateUtils.dateToInteger(DateUtils.str2DateByFormat(t.getReissueStartTime(),"yyyy-MM-dd HH:mm")));
            } else {
                temp.setOrderStartIndex(DateUtils.dateToInteger(DateUtils.stringToDate2(t.getReissueStartTime())));
            }
        }
        if (StringUtils.isNotEmpty(t.getReissueEndTime())) {
            temp.setOrderEndTime(t.getReissueEndTime());
            if (t.getReissueEndTime().length()==16){
                temp.setOrderEndIndex(DateUtils.dateToInteger(DateUtils.str2DateByFormat(t.getReissueEndTime(),"yyyy-MM-dd HH:mm")));
            } else {
                temp.setOrderEndIndex(DateUtils.dateToInteger(DateUtils.stringToDate2(t.getReissueEndTime())));
            }
        }
        if (!CollectionUtils.isEmpty(t.getExcludePlayerAccountNoList())){
            temp.setExcludePlayerAccountNoList(t.getExcludePlayerAccountNoList());
        }
        PageInfo<ReissueOrderDTO> pageInfo = orderService.selectRechargeNumbers(temp);
        if (CollectionUtils.isEmpty(pageInfo.getList())) {
            return new ArrayList<>();
        }
        MerchantDTO merchantDTO = new MerchantDTO();
        merchantDTO.setId(t.getMerchantId());
        List<ReissueRecord> rrList=new ArrayList<>();
        for (ReissueOrderDTO reissueOrder : pageInfo.getList()) {
            ReissueRecord reissueRecord = new ReissueRecord();
            reissueRecord.setRatId(t.getId());
            reissueRecord.setPartitionId(t.getPartitionId());
            reissueRecord.setPartitionName(reissueOrder.getPartitionName());
            reissueRecord.setMerchantId(t.getMerchantId());
            reissueRecord.setOperatorId(t.getOperatorId());
            reissueRecord.setOperateIp(t.getOperateIp());
            reissueRecord.setReissueType(ReissueType.WHOLE);
            reissueRecord.setRechargeNumber(reissueOrder.getRechargeNumber());
            reissueRecord.setRechargeAmount(reissueOrder.getAmount());
            reissueRecord.setChannelName(reissueOrder.getPayTypeName());
            reissueRecord.setCode(reissueOrder.getPayCode());
            Date date = new Date();
            reissueRecord.setExchangeTime(date);
            reissueRecord.setScriptStatus(2);
            reissueRecord.setExchangeTimeIndex(DateUtils.dateToInteger(date));
            reissueRecord.setSerialNumber("CA".concat(SnowFlakeUtils.getUniqueId()));
            reissueRecord.setOrderNo(reissueOrder.getOrderNo());
            if(isAutoReissue==0) {
                reissueRecordMapper.insertSelective(reissueRecord);
            }
            rrList.add(reissueRecord);
        }

        return rechargeAll(rrList,t,typeOne,typeTwo,typeThree,partition);
    }

    /**
     * 整区补发-按玩家充值成功订单条件补发
     * @param reissueAllTask
     * @return
     */
    @Override
    public void rechargeAllGetWay(List<GameRechargeGetWayDTO> rechargelist,Partition partition , ReissueAllTask reissueAllTask) {

      String traceId = SnowFlakeUtils.getUniqueId();
        try {
            if (CollectionUtils.isEmpty(rechargelist)) {
                reissueAllTask.setReissueStatus(1);
                return ;
            }
            GameRechargeGetWayCollectionDTO grgwcDTO = new GameRechargeGetWayCollectionDTO();
            Merchant merchant = merchantService.find(reissueAllTask.getMerchantId());
            grgwcDTO.setList(rechargelist);
            String url = partition.getServiceAgreement() + "://" + partition.getServerIp() + ":" + partition.getPortNum();
            CommonResult result = HttpClientUtils.doPostGetWay(url + RequestConfig.GETWAY_RECHARGE_GROUP_URL,
                    grgwcDTO, merchant.getPrivateKey(),traceId);
            switch(result.getCode()){
                case 200 :
                    reissueAllTask.setReissueStatus(1);
                    LogPortal.info("{} 整区补发-按玩家充值成功记录补发 发送支付网关成功，支付网关业务处理成功 商户ID[{}] 分区ID[{}] 分区名称[{}] 条件ID[{}]",traceId,reissueAllTask.getMerchantId(),reissueAllTask.getPartitionId(),reissueAllTask.getPartitionName(),reissueAllTask.getId());
                    break;
                case -1 :
                    LogPortal.error("{} SEND_WHOLE_AREA_PLAYER_RECHARGE_GATEWAY_FAIL 整区补发-按玩家充值成功记录补发 发送支付网关失败，支付网关业务处理失败 商户ID[{}] 分区ID[{}] 分区名称[{}] 条件ID[{}] 失败描述：[{}]",traceId,reissueAllTask.getId(), reissueAllTask.getPartitionName(), result.getMsg());
                    reissueAllTask.setReissueStatus(-1);
                    break;
                case 203 :
                    LogPortal.error("{} SEND_WHOLE_AREA_PLAYER_RECHARGE_GATEWAY_FAIL 整区补发-按玩家充值成功记录补发 发送支付网关失败，支付网关业务处理失败 商户ID[{}] 分区ID[{}] 分区名称[{}] 条件ID[{}] 失败描述：[{}]",traceId,reissueAllTask.getId(), reissueAllTask.getPartitionName(), result.getMsg());
                    reissueAllTask.setReissueStatus(-1);
                    break;
                case 800 :
                    LogPortal.error("{} SEND_WHOLE_AREA_PLAYER_RECHARGE_GATEWAY_CONNECT_TIMEOUT_FAIL 整区补发-按玩家充值成功记录补发 发送支付网关失败，支付网关连接失败 商户ID[{}] 分区ID[{}] 分区名称[{}] 条件ID[{}] 失败描述：[{}]",traceId,reissueAllTask.getMerchantId(),reissueAllTask.getPartitionId(),reissueAllTask.getPartitionName(),reissueAllTask.getId(),result.getMsg());
                    reissueAllTask.setReissueStatus(-1);
                    break;
                case 801 :
                    LogPortal.error("{} SEND_WHOLE_AREA_PLAYER_RECHARGE_GATEWAY_SOCKET_TIMEOUT_FAIL 整区补发-按玩家充值成功记录补发 发送支付网关成功，支付网关响应超时 商户ID[{}] 分区ID[{}] 分区名称[{}] 条件ID[{}] 失败描述：[{}]", traceId,reissueAllTask.getMerchantId(),reissueAllTask.getPartitionId(),reissueAllTask.getPartitionName(),reissueAllTask.getId(),result.getMsg());
                    reissueAllTask.setReissueStatus(-1);
                    break;
                case 802 :
                    LogPortal.error("{} SEND_WHOLE_AREA_PLAYER_RECHARGE_GATEWAY_EXCEPTION_FAIL 整区补发-按玩家充值成功记录补发 发送支付网关失败，支付网关业务处理发生了其他异常 商户ID[{}] 分区ID[{}] 分区名称[{}] 条件ID[{}] 失败描述：[{}]",traceId,reissueAllTask.getMerchantId(),reissueAllTask.getPartitionId(),reissueAllTask.getPartitionName(),reissueAllTask.getId(),result.getMsg());
                    reissueAllTask.setReissueStatus(-1);
                    break;
                default:
            }
        } catch (Exception e) {
            reissueAllTask.setReissueStatus(-1);
            LogPortal.error("{} CREATE_WHOLE_AREA_PLAYER_RECHARGE_GATEWAY_EXCEPTION_FAIL 创建整区补发-按玩家充值成功记录补发失败，发生了{}异常 商户ID[{}] 分区ID[{}] 分区名称[{}] 条件ID[{}] 失败描述：[{}]",traceId,e.getClass().getName(),reissueAllTask.getMerchantId(),reissueAllTask.getPartitionId(),reissueAllTask.getPartitionName(),reissueAllTask.getId(), e.getMessage());
            LogPortal.error("{} 创建整区补发-按玩家充值成功记录补发失败 发生了{}异常 商户ID[{}] 分区ID[{}] 分区名称[{}] 条件ID[{}] 失败描述：[{}]",e,traceId,e.getClass().getName(),reissueAllTask.getMerchantId(),reissueAllTask.getPartitionId(),reissueAllTask.getPartitionName(),reissueAllTask.getId(), e.getMessage());
        }
    }


    @Override
    public void update(ReissueRecord t) {

    }

    @Override
    public void del(ReissueRecord t) {
        reissueRecordMapper.deleteByPrimaryKey(t.getId());
    }

    public void delByIds(String[] Ids){
        reissueRecordMapper.delByIds(Ids);
    }

    @Override
    public ReissueRecord find(Integer merchantId, String id) {
        ReissueRecord reissueRecord = reissueRecordMapper.selectById(merchantId, id);
        return reissueRecord;
    }

    /**
     * 手动补发
     * @param merchantId
     * @param reissueRecordId
     * @return
     */
    @Override
    public CommonResult<T> rechargeGetWay(Integer merchantId, String reissueRecordId) {
        String traceId = SnowFlakeUtils.getUniqueId();
        ReissueRecord reissueRecord = reissueRecordMapper.selectByPrimaryKey(reissueRecordId);
        String partitionName = "";
        String partitionId="";
        try {
            Merchant merchant = merchantService.find(merchantId);
            Partition partition = partitionService.find(merchant.getId(), reissueRecord.getPartitionId());
            partitionName = partition.getPartitionName();
            partitionId = partition.getId();
            TemplateCriteria template = templateService.selectTemById(partition.getTemplateId());
            ReissueRecordD reissueRecordDTO = BeanConvertUtils.convert(reissueRecord, ReissueRecordD.class);
            PartitionDTO partitionDTO = BeanConvertUtils.convert(partition, PartitionDTO.class);
            GameRechargeGetWayDTO gameRechargeGetWayDTO = partitionRemoteService.rechargeGetWay(reissueRecordDTO, partitionDTO, template);
            String url = partition.getServiceAgreement() + "://" + gameRechargeGetWayDTO.getServerIp() + ":" + gameRechargeGetWayDTO.getPortNum();
            CommonResult result = HttpClientUtils.doPostGetWay(url + RequestConfig.GETWAY_RECHARGE_URL,
                    gameRechargeGetWayDTO, merchant.getPrivateKey(),traceId,5);

            switch(result.getCode()){
                case 200 :
                    reissueRecord.setScriptStatus(1);
                    result.setMsg("充值成功");
                    LogPortal.info("{} 手动补发 发送支付网关成功，支付网关业务处理成功 玩家账号[{}] 商户订单号[{}] 商户ID[{}] 分区ID[{}] 分区名称[{}]",traceId,reissueRecord.getRechargeNumber(),reissueRecord.getSerialNumber(),merchantId,partitionId,partition.getPartitionName());
                    break;
                case -1 :
                    LogPortal.error("{} SEND_MANUAL_REISSUE_GATEWAY_RECHARGE_FAIL 手动补发 发送支付网关成功，支付网关业务处理失败 玩家账号[{}] 商户订单号[{}] 商户ID[{}] 分区ID[{}] 分区名称[{}] 失败描述：[{}]",traceId, reissueRecord.getRechargeNumber(), reissueRecord.getSerialNumber(),merchantId,partitionId,partition.getPartitionName(), result.getMsg());
                    reissueRecord.setScriptStatus(-1);
                    result.setMsg("充值失败");
                    break;
                case 203 :
                    LogPortal.error("{} SEND_MANUAL_REISSUE_GATEWAY_RECHARGE_FAIL 手动补发 发送支付网关失败，支付网关业务处理失败 玩家账号[{}] 商户订单号[{}] 商户ID[{}] 分区ID[{}] 分区名称[{}] 失败描述：[{}]",traceId, reissueRecord.getRechargeNumber(), reissueRecord.getSerialNumber(),merchantId,partitionId,partition.getPartitionName(), result.getMsg());
                    reissueRecord.setScriptStatus(-1);
                    result.setMsg("充值失败");
                    break;
                case 800 :
                    LogPortal.error("{} SEND_MANUAL_REISSUE_GATEWAY_CONNECT_TIMEOUT_FAIL 手动补发 发送支付网关失败，支付网关连接失败 玩家账号[{}] 商户订单号[{}] 商户ID[{}] 分区ID[{}] 分区名称[{}] 失败描述：[{}]",traceId,reissueRecord.getRechargeNumber(),reissueRecord.getSerialNumber(),merchantId,partitionId,partition.getPartitionName(), result.getMsg());
                    reissueRecord.setScriptStatus(-1);
                    result.setMsg("充值失败");
                    break;
                case 801 :
                    LogPortal.error("{} SEND_MANUAL_REISSUE_GATEWAY_SOCKET_TIMEOUT_FAIL 手动补发 发送支付网关成功，支付网关响应超时 玩家账号[{}] 商户订单号[{}] 商户ID[{}] 分区ID[{}] 分区名称[{}] 失败描述：[{}]",traceId, reissueRecord.getRechargeNumber(),reissueRecord.getSerialNumber(),merchantId,partitionId,partition.getPartitionName(), result.getMsg());
                    reissueRecord.setScriptStatus(2);
                    result.setMsg("充值处理中");
                    break;
                case 802 :
                    LogPortal.error("{} SEND_MANUAL_REISSUE_GATEWAY_EXCEPTION_FAIL 手动补发 发送支付网关失败，支付网关发生了其他异常 玩家账号[{}] 商户订单号[{}] 商户ID[{}] 分区ID[{}] 分区名称[{}] 失败描述：[{}]",traceId, reissueRecord.getRechargeNumber(), reissueRecord.getSerialNumber(),merchantId,partitionId,partition.getPartitionName(), result.getMsg());
                    reissueRecord.setScriptStatus(-1);
                    result.setMsg("充值失败");
                    break;
                default:
            }
           return result;
        } catch (Exception e) {
            LogPortal.error("{} SEND_MANUAL_REISSUE_GATEWAY_EXCEPTION_FAIL 手动补发 发送支付网关失败，支付网关发生了{}异常 玩家账号[{}] 商户订单号[{}] 商户ID[{}] 分区ID[{}] 分区名称[{}] 失败描述：[{}]",traceId,e.getClass().getName(),reissueRecord.getRechargeNumber(),reissueRecord.getSerialNumber(),merchantId,partitionId,partitionName,e.getMessage());
            LogPortal.error("{} 手动补发 发送支付网关失败，支付网关发生了{}异常 玩家账号[{}] 商户订单号[{}] 商户ID[{}] 分区ID[{}] 分区名称[{}] 失败描述：[{}]",e,traceId,e.getClass().getName(),reissueRecord.getRechargeNumber(),reissueRecord.getSerialNumber(),merchantId,partitionId,partitionName,e.getMessage());
            reissueRecord.setScriptStatus(-1);
            return new CommonResult(CommonConstants.RETURN_ERROR, "充值失败", "");
        }finally {
            reissueRecordMapper.updateByPrimaryKeySelective(reissueRecord);
        }

    }

    @Override
    @Transactional
    public String manualTopUp(ReissueRecordCriteria manualCriteria) {
        if (manualCriteria == null) {
            throw new ParameterException("参数不能为空");
        }
        if (StringUtils.isBlank(manualCriteria.getRechargeNumber())) {
            throw new ParameterException("游戏账号不能为空");
        }
        if (StringUtils.isBlank(manualCriteria.getPartitionId())) {
            throw new ParameterException("分区不能为空");
        }
        if (manualCriteria.getRechargeAmount().equals(new BigDecimal(0))) {
            throw new ParameterException("充值金额不能为空");
        }
        if (StringUtils.isBlank(manualCriteria.getCode())) {
            throw new ParameterException("充值方式不能为空");
        }
        if (!partitionService.isHavePartitionById(manualCriteria.getPartitionId())) {
            throw new ParameterException("分区id传入错误");
        }
        manualCriteria.setReissueType(ReissueType.MANUAL);
        Date date = new Date();
        manualCriteria.setExchangeTime(date);
        manualCriteria.setExchangeTimeIndex(DateUtils.dateToInteger(date));
        if (StringUtils.isEmpty(manualCriteria.getSerialNumber())) {
            manualCriteria.setSerialNumber(SerialNumberUtil.getSerialNumber());
        }
        if(StringUtils.isEmpty(manualCriteria.getManualType())){
            manualCriteria.setManualType(" ");
        }
        if (StringUtils.isEmpty(manualCriteria.getPartitionName())){
            PartitionDTO partitionDTO = partitionService.getPartitionInfoById(manualCriteria.getPartitionId());
            if (partitionDTO != null){
                manualCriteria.setPartitionName(partitionDTO.getPartitionName());
            }
        }
        ReissueRecord reissueRecord = BeanConvertUtils.convert(manualCriteria, ReissueRecord.class);
        reissueRecordMapper.insertSelective(reissueRecord);
        return reissueRecord.getId();
    }

    @Override
    public PageInfo selectAllManual(ReissueRecordSelectCriteria selectCriteria) {
        if (selectCriteria == null) {
            throw new ParameterException("参数不能为空");
        }
        selectCriteria.setReissueType(ReissueType.MANUAL.name());
        if (selectCriteria.getPageNum() == 0 || selectCriteria.getPageSize() == 0) {
            throw new ParameterException("分页查询条件错误");
        }
        PageHelper.startPage(selectCriteria.getPageNum(), selectCriteria.getPageSize());
        List<ReissueRecordDTO> reissueRecordDTOS = reissueRecordMapper.selectByPage(selectCriteria);
        return new PageInfo(reissueRecordDTOS);
    }

    @Override
    public boolean sendGateWayWholeReplacement(ReplacementGetWayDTO dto) {
        String traceId = SnowFlakeUtils.getUniqueId();
        ReissueAllTask reissueAllTask =reissueAllTaskService.selectOne(dto.getRatId());
        try {
            GameRechargeGetWayCollectionDTO grgwcDTO = new GameRechargeGetWayCollectionDTO();
            List<GameRechargeGetWayDTO> grgwlist=dto.getList();
            grgwcDTO.setList(grgwlist);
            Merchant merchant = merchantService.find(dto.getMerchantId());
            Partition partition = partitionService.find(merchant.getId(), dto.getPartitionId());
            String url = partition.getServiceAgreement() + "://" + partition.getServerIp() + ":" + partition.getPortNum();
            CommonResult result = HttpClientUtils.doPostGetWay(url + RequestConfig.GETWAY_RECHARGE_GROUP_URL,
                    grgwcDTO, merchant.getPrivateKey(), traceId);
            switch (result.getCode()) {
                case 200:
                    reissueAllTask.setReissueStatus(1);
                    StringBuffer serialNumbersBuffer=new StringBuffer();
                    int listSize=grgwlist.size();
                    int lastSize=listSize-1;
                    for(int i=0;i<listSize;i++){
                        serialNumbersBuffer.append(grgwlist.get(i).getOrderNo());
                        if(i<lastSize){
                            serialNumbersBuffer.append(",");
                        }
                    }
                    reissueRecordMapper.updateWholeReplacement(serialNumbersBuffer.toString());
                    LogPortal.info("{}   候补整区补发-按玩家充值成功记录补发 发送支付网关成功，支付网关业务处理成功 商户ID[{}] 分区ID[{}] 分区名称[{}] 条件ID[{}]", traceId, reissueAllTask.getMerchantId(), reissueAllTask.getPartitionId(), reissueAllTask.getPartitionName(), reissueAllTask.getId());
                    return true;
                case -1:
                    LogPortal.error("{}   候补整区补发-按玩家充值成功记录补发 发送支付网关失败，支付网关业务处理失败 商户ID[{}] 分区ID[{}] 分区名称[{}] 条件ID[{}] 失败描述：[{}]", traceId, reissueAllTask.getId(), reissueAllTask.getPartitionName(), result.getMsg());
                    break;
                case 203:
                    LogPortal.error("{}   候补整区补发-按玩家充值成功记录补发 发送支付网关失败，支付网关业务处理失败 商户ID[{}] 分区ID[{}] 分区名称[{}] 条件ID[{}] 失败描述：[{}]", traceId, reissueAllTask.getId(), reissueAllTask.getPartitionName(), result.getMsg());
                    break;
                case 800:
                    LogPortal.error("{}   候补整区补发-按玩家充值成功记录补发 发送支付网关失败，支付网关连接失败 商户ID[{}] 分区ID[{}] 分区名称[{}] 条件ID[{}] 失败描述：[{}]", traceId, reissueAllTask.getMerchantId(), reissueAllTask.getPartitionId(), reissueAllTask.getPartitionName(), reissueAllTask.getId(), result.getMsg());
                    break;
                case 801:
                    LogPortal.error("{}   候补整区补发-按玩家充值成功记录补发 发送支付网关成功，支付网关响应超时 商户ID[{}] 分区ID[{}] 分区名称[{}] 条件ID[{}] 失败描述：[{}]", traceId, reissueAllTask.getMerchantId(), reissueAllTask.getPartitionId(), reissueAllTask.getPartitionName(), reissueAllTask.getId(), result.getMsg());
                    // 待处理...................
                    break;
                case 802:
                    LogPortal.error("{}  候补整区补发-按玩家充值成功记录补发 发送支付网关失败，支付网关业务处理发生了其他异常 商户ID[{}] 分区ID[{}] 分区名称[{}] 条件ID[{}] 失败描述：[{}]", traceId, reissueAllTask.getMerchantId(), reissueAllTask.getPartitionId(), reissueAllTask.getPartitionName(), reissueAllTask.getId(), result.getMsg());
                    break;
                default:
            }
        }catch (Exception e){
             LogPortal.error("{}  候补整区补发-按玩家充值成功记录补发 发送支付网关失败，支付网关业务处理发生了其他异常 商户ID[{}] 分区ID[{}] 分区名称[{}] 条件ID[{}] 失败描述：[{}]",e, traceId, reissueAllTask.getMerchantId(), reissueAllTask.getPartitionId(), reissueAllTask.getPartitionName(), reissueAllTask.getId(), e.getMessage());
        }finally {
            reissueAllTaskService.update(reissueAllTask);
        }
        return false;
    }

    @Override
    public boolean sendGateWayManualReplacement(ReplacementGetWayDTO dto) {
        String traceId = SnowFlakeUtils.getUniqueId();
        try {
            GameRechargeGetWayDTO gameRechargeGetWay=dto.getGameRechargeGetWay();
            Merchant merchant = merchantService.find(dto.getMerchantId());
            Partition partition = partitionService.find(merchant.getId(), dto.getPartitionId());
            String url = partition.getServiceAgreement() + "://" + partition.getServerIp() + ":" + partition.getPortNum();
            CommonResult result = HttpClientUtils.doPostGetWay(url + RequestConfig.GETWAY_RECHARGE_URL,
                    gameRechargeGetWay, merchant.getPrivateKey(), traceId);
            switch (result.getCode()) {
                case 200:
                    if("手动补发".equals(gameRechargeGetWay.getRechargeType())) {
                        reissueRecordMapper.updateManualReplacement(gameRechargeGetWay.getOrderNo(), 1);
                    }else{
                        Order order=new Order();
                        order.setMerchantOrderNo(gameRechargeGetWay.getOrderNo());
                        order.setScriptStatus(1);
                        orderService.updateScriptStatus(order);
                    }
                    LogPortal.info("{}   候补手动充值补发-按玩家充值成功记录补发 发送支付网关成功，支付网关业务处理成功 商户ID[{}] 分区ID[{}] 分区名称[{}] 条件ID[{}]", traceId, dto.getMerchantId(), dto.getPartitionId(), dto.getPartitionName(), dto.getGameRechargeGetWay().getOrderNo());
                    return true;
                case -1:
                    LogPortal.error("{}   候补手动充值补发-按玩家充值成功记录补发 发送支付网关失败，支付网关业务处理失败 商户ID[{}] 分区ID[{}] 分区名称[{}] 条件ID[{}] 失败描述：[{}]", traceId, dto.getMerchantId(), dto.getPartitionId(), dto.getPartitionName(), dto.getGameRechargeGetWay().getOrderNo(), result.getMsg());
                    break;
                case 203:
                    LogPortal.error("{}   候补手动充值补发-按玩家充值成功记录补发 发送支付网关失败，支付网关业务处理失败 商户ID[{}] 分区ID[{}] 分区名称[{}] 条件ID[{}] 失败描述：[{}]", traceId, dto.getMerchantId(), dto.getPartitionId(), dto.getPartitionName(), dto.getGameRechargeGetWay().getOrderNo(), result.getMsg());
                    break;
                case 800:
                    LogPortal.error("{}   候补手动充值补发-按玩家充值成功记录补发 发送支付网关失败，支付网关连接失败 商户ID[{}] 分区ID[{}] 分区名称[{}] 条件ID[{}] 失败描述：[{}]", traceId, dto.getMerchantId(), dto.getPartitionId(), dto.getPartitionName(), dto.getGameRechargeGetWay().getOrderNo(), result.getMsg());
                    break;
                case 801:
                    LogPortal.error("{}   候补手动充值补发-按玩家充值成功记录补发 发送支付网关成功，支付网关响应超时 商户ID[{}] 分区ID[{}] 分区名称[{}] 条件ID[{}] 失败描述：[{}]", traceId, dto.getMerchantId(), dto.getPartitionId(), dto.getPartitionName(), dto.getGameRechargeGetWay().getOrderNo(), result.getMsg());
                    // 待处理...................
                    break;
                case 802:
                    LogPortal.error("{}  候补手动充值补发-按玩家充值成功记录补发 发送支付网关失败，支付网关业务处理发生了其他异常 商户ID[{}] 分区ID[{}] 分区名称[{}] 条件ID[{}] 失败描述：[{}]", traceId, dto.getMerchantId(), dto.getPartitionId(), dto.getPartitionName(), dto.getGameRechargeGetWay().getOrderNo(), result.getMsg());
                    break;
                default:
            }
        }catch (Exception e){
            LogPortal.error("{}  候补手动充值补发-按玩家充值成功记录补发 发送支付网关失败，支付网关业务处理发生了其他异常 商户ID[{}] 分区ID[{}] 分区名称[{}] 条件ID[{}] 失败描述：[{}]",e, traceId, dto.getMerchantId(), dto.getPartitionId(), dto.getPartitionName(), dto.getGameRechargeGetWay().getOrderNo(), e.getMessage());
        }
        return false;
    }

    @Override
    public boolean sendGateWayCheckOrder(CheckOrderIDGateWayDTO dto) {
        String traceId = SnowFlakeUtils.getUniqueId();
        try {
            Merchant merchant = merchantService.find(dto.getMerchantId());
            Partition partition = partitionService.find(merchant.getId(), dto.getPartitionId());
            String url = partition.getServiceAgreement() + "://" + partition.getServerIp() + ":" + partition.getPortNum();
            CommonResult result = HttpClientUtils.doPostGetWay(url + RequestConfig.GETWAY_CHECK_ORDER_URL,
                    dto.getOrderNo(), merchant.getPrivateKey(), traceId);
            switch (result.getCode()) {
                case 200:
                    if("Rep".equals(dto.getRechargeType())) {
                        reissueRecordMapper.updateManualReplacement(dto.getOrderNo(), 1);
                    }else{
                        Order order=new Order();
                        order.setMerchantOrderNo(dto.getOrderNo());
                        order.setScriptStatus(1);
                        orderService.updateScriptStatus(order);
                    }
                    LogPortal.info("{}   检查订单-按订单单号 脚本发送支付网关成功，支付网关脚本处理成功 商户ID[{}] 分区ID[{}] 分区名称[{}] 条件ID[{}]", traceId, dto.getMerchantId(), dto.getPartitionId(), dto.getPartitionName(), dto.getOrderNo());
                    return true;
                case -1:
                    LogPortal.error("{}  检查订单-按订单单号 脚本发送支付网关成功，支付网关脚本处理未完成或失败 商户ID[{}] 分区ID[{}] 分区名称[{}] 条件ID[{}] 失败描述：[{}]", traceId, dto.getMerchantId(), dto.getPartitionId(), dto.getPartitionName(), dto.getOrderNo(), result.getMsg());
                    break;
                case 203:
                    LogPortal.error("{}  检查订单-按订单单号 脚本发送支付网关成功，支付网关脚本处理未完成或失败 商户ID[{}] 分区ID[{}] 分区名称[{}] 条件ID[{}] 失败描述：[{}]", traceId, dto.getMerchantId(), dto.getPartitionId(), dto.getPartitionName(), dto.getOrderNo(), result.getMsg());
                    break;
                case 800:
                    LogPortal.error("{}  检查订单-按订单单号 脚本发送支付网关成功，支付网关连接失败 商户ID[{}] 分区ID[{}] 分区名称[{}] 条件ID[{}] 失败描述：[{}]", traceId, dto.getMerchantId(), dto.getPartitionId(), dto.getPartitionName(), dto.getOrderNo(), result.getMsg());
                    break;
                case 801:
                    LogPortal.error("{}  检查订单-按订单单号 脚本发送支付网关成功，支付网关响应超时 商户ID[{}] 分区ID[{}] 分区名称[{}] 条件ID[{}] 失败描述：[{}]", traceId, dto.getMerchantId(), dto.getPartitionId(), dto.getPartitionName(), dto.getOrderNo(), result.getMsg());
                    // 待处理...................
                    break;
                case 802:
                    LogPortal.error("{}  检查订单-按订单单号 脚本发送支付网关成功，支付网关业务处理发生了其他异常 商户ID[{}] 分区ID[{}] 分区名称[{}] 条件ID[{}] 失败描述：[{}]", traceId, dto.getMerchantId(), dto.getPartitionId(), dto.getPartitionName(), dto.getOrderNo(), result.getMsg());
                    break;
                default:
            }
        }catch (Exception e){
            LogPortal.error("{}  检查订单-按订单单号 脚本发送支付网关成功 发送支付网关失败，异常 商户ID[{}] 分区ID[{}] 分区名称[{}] 条件ID[{}] 失败描述：[{}]",e, traceId, dto.getMerchantId(), dto.getPartitionId(), dto.getPartitionName(), dto.getOrderNo(), e.getMessage());
        }
        return false;
    }

    @Override
    public void updateManualReplacement(String serialNumbers, int scriptStatus) {
        reissueRecordMapper.updateManualReplacement(serialNumbers,scriptStatus);
    }

    @Override
    public void updateReissueAllTasks(String ratId, int scriptStatus) {
        reissueRecordMapper.updateReissueAllTasks(ratId,scriptStatus);
    }

    @Override
    public GameRechargeGetWayDTO manualGiveDetail(ReissueRecordCriteria manualCriteria) {
        Partition partition = partitionService.find(manualCriteria.getMerchantId(), manualCriteria.getPartitionId());
        TemplateCriteria template = templateService.selectTemById(partition.getTemplateId());
        PartitionDTO partitionDTO = BeanConvertUtils.convert(partition, PartitionDTO.class);
        ReissueRecordD reissueRecordDTO = BeanConvertUtils.convert(manualCriteria, ReissueRecordD.class);
        GameRechargeGetWayDTO gameRechargeGetWayDTO = partitionRemoteService.rechargeGetWay(reissueRecordDTO, partitionDTO, template);
        return gameRechargeGetWayDTO;
    }
}




